#include "../../core/pch.h"
#include "../utils/utils.c"
#include "../../pi/BinarySemaphore.h"

/**
 * Pointer for shared memory.
 */
struct info_table* shared_memory;

/**
 * Id identifying shared memory segment id.
 */
int segment_id;

/**
 * Semaphore id which will be used to synchornize master
 * processes.
 */
int sem_id;

struct prime_str ret;

int main(int argc, char** argv)
{
	DEBUGS("sender: running");

	segment_id = atoi(argv[1]);
	sem_id = atoi(argv[2]);

	/**
	 * Attach the shared memory segment.
	 */
	shared_memory = (struct info_table*) shmat(segment_id, NULL, 0);

	/**
	 * While there's an idle computer send to it factorization request.
	 * If there's no idle computer sleep, LOGGER process will wake up
	 * this process if it finds that one of the computers is idle.
	 */
	struct sockaddr_in worker_addr;
	int worker_sock;
	char msg;
	FILE* primesFile = fopen("../../data/primes", "r+b");
	PF_clear_primes(primesFile);
	while (true)
	{
		BinarySemaphore::Decrement(sem_id);

		DEBUGS("sender: looking for idle computer");

		for (int i = 0; i < shared_memory->count; i++)
		{
			if (shared_memory->NUMBER == 1)
			{
				fclose(primesFile);
				exit(0);
			}

			if (shared_memory->idle[i] && shared_memory->alive[i])
			{
				DEBUGS("sender: connecting to idle computer (%s, %d)", shared_memory->ip[i], shared_memory->port[i]);

				memset(&worker_addr, 0, sizeof(worker_addr));
				worker_addr.sin_family = AF_INET;
				worker_addr.sin_port = htons(shared_memory->worker_port[i]);
				inet_pton(AF_INET, shared_memory->ip[i], &worker_addr.sin_addr);

				worker_sock = socket(AF_INET, SOCK_STREAM, 0);
				connect(worker_sock, (struct sockaddr*) &worker_addr, sizeof(worker_addr));

				/** Get first not send prime number. */
				ret = PF_get_first_not_sent(primesFile);
				PF_set_sent(ret.number, primesFile);

				DEBUGS("sender: send number %d", ret.value);

				
				msg = FACTOR_REQUEST;
				send(worker_sock, &msg, sizeof(char), 0);
				send(worker_sock, &shared_memory->NUMBER, sizeof(unsigned int), 0);
				send(worker_sock, &ret.value, sizeof(unsigned int), 0);

				shared_memory->idle[i] = 0;

				close(worker_sock);
			}
		}

		BinarySemaphore::Increment(sem_id);

		sleep(4);
	}

	fclose(primesFile);

	return 0;
}

